package com.snap.vseries.fragment;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Spinner;

import android.widget.TextView;

import androidx.annotation.RequiresApi;

import com.snap.vseries.Constants;
import com.snap.vseries.R;
import com.snap.vseries.adapter.HomeTemplateAdapter;
import com.snap.vseries.adapter.SpinnerAdapter;
import com.snap.vseries.base.BaseFragment;
import com.snap.vseries.bean.ExpEntity;
import com.snap.vseries.model.DBManager;
import com.snap.vseries.service.ExpController;
import com.snap.vseries.service.ExpException;
import com.snap.vseries.service.PcrService;
import com.snap.vseries.service.OnExpStateChangedListener;
import com.snap.vseries.ui.ExpNewExperimentActivity;
import com.snap.vseries.ui.ExpResultActivity;
import com.snap.vseries.ui.ExpRunningActivity;
import com.snap.vseries.ui.TemplatesManagerActivity;
import com.snap.vseries.ui.widget.DialogView;
import com.snap.vseries.ui.widget.ProgressBar;
import com.snap.vseries.ui.widget.SideSlipLayout;
import com.snap.vseries.ui.widget.TextButton;
import com.snap.vseries.utils.AutoUtil;
import com.snap.vseries.utils.ToastUtils;

import org.litepal.crud.callback.FindMultiCallback;

import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

import butterknife.BindView;
import butterknife.OnClick;

import static android.content.Context.BIND_AUTO_CREATE;


public class HomeFragment extends BaseFragment {
    private static final String TAG = "HomeFragment";
    private static final int MSG_RENDER = 99;
    @BindView(R.id.template_rv)
    RecyclerView templateRv;
    @BindView(R.id.connect_wrapper_fl)
    FrameLayout connectWrapperFl;
    @BindView(R.id.device_display_ll)
    LinearLayout deviceDisplayLl;
    @BindView(R.id.exp_run_btn)
    TextButton expRunBtn;

    @BindView(R.id.side_slip_layout)
    SideSlipLayout sideSlipLayout;
    @BindView(R.id.stop_exp_tv)
    TextView stopExpTv;
    @BindView(R.id.background_fl)
    FrameLayout backgroundFl;

    @BindView(R.id.spinner)
    Spinner spinner;

    private UiHandler renderHandler = new UiHandler(this);
    private LinearLayout expRunningLl;
    private ConstraintLayout expFinishedCl;
    private TextButton expNewBtn;
    /**
     * 进度条+进度条文字
     */
    private ProgressBar progressView;
    private TextView processTv;
    private TextView startTimeTv;
    private TextView endTimeTv;
    private TextView leftTimeTv;
    private ExpController currentController;

    private HomeTemplateAdapter templateAdapter;
    private PcrService mService;
    /**
     * 监听实验状态
     */
    private OnExpStateChangedListener stateListener = new OnExpStateChangedListener() {
        @Override
        public void onStateChanged() {
            HomeFragment.this.changeExpState(currentController.getExpState());
        }
    };

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            PcrService.PcrBinder binder = (PcrService.PcrBinder) service;
            mService = binder.getService();
            currentController = binder.getService().getCurrentController();
            mService.registerOnExpStateChangedListener(stateListener);
            changeExpColumnState(currentController.getExpState());
            showSpinner();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }

    };



    private void changeExpState(int newState) {
        HomeFragment.this.changeExpColumnState(newState);
    }

    @Override
    protected int layoutResId() {
        return R.layout.fragment_home;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initView();
        bindService();
    }
    /**
     * 下拉框选择列表
     **/
    private void showSpinner() {
        List<String> controllerList= mService.getControllerList();
        int selection = 0;

        for (int i = 0; i < controllerList.size(); i++) {
            String content = controllerList.get(i);
            if (content.equals(mService.getCurrentKey())) {
                selection = i;
            }
        }
        SpinnerAdapter spinnerAdapter = new SpinnerAdapter(getContext(), controllerList);
        spinner.setAdapter(spinnerAdapter);
        spinner.setSelection(selection);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void onItemSelected(AdapterView<?> parent, View view,
                                       int position, long id) {
                TextView tv = (TextView) view;
                if (tv != null) {
                    tv.setPadding(0, 0, 0, 0);
                    tv.setTextColor(getResources().getColor(R.color.white));
                    tv.setTextSize(12);
                }
                mService.setCurrentKey(controllerList.get(position));
                currentControllerChanged();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    }

    private void currentControllerChanged() {
        currentController=mService.getCurrentController();
        if (currentController != null) {
            changeExpColumnState(currentController.getExpState());
        }
    }
    /**
     * 打开service 打开串口
     */
    private void bindService() {
        Intent intent = new Intent(getContext(), PcrService.class);
        Objects.requireNonNull(getActivity()).bindService(intent, connection, BIND_AUTO_CREATE);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mActivity != null) {
            if (mService != null) {
                mService.unregisterOnExpStateChangedListener(stateListener);
            }
            mActivity.unbindService(connection);
        }
    }

    private void setFlBackground(int expState) {
        switch (expState) {
            case Constants.EXP_STATE_IDLE:
                backgroundFl.setBackground(getActivity().getResources().getDrawable(R.drawable.pic_panel_home));
                break;
            case Constants.EXP_STATE_RUNNING:
                backgroundFl.setBackground(getActivity().getResources().getDrawable(R.drawable.pic_panel_home));
                break;
            case Constants.EXP_STATE_FINISH:
                backgroundFl.setBackground(getActivity().getResources().getDrawable(R.drawable.pic_panel_finish));
                break;
            case Constants.EXP_STATE_INTERRUPT:
                backgroundFl.setBackground(getActivity().getResources().getDrawable(R.drawable.pic_panel_finish));
                break;
            default:
        }
    }

    private void initView() {
        initStopButton();
        //检验项目模块
        initTestProjects();
        //实验面板-设备的实验状态
        addExperimentStatusView();
    }

    private void notifyTestProjects() {
        DBManager.get().getTemplateList(new FindMultiCallback<ExpEntity>() {
            @Override
            public void onFinish(List<ExpEntity> list) {
                if (templateAdapter != null) {
                    templateAdapter.updateData(list);
                }
            }
        });
    }


    private void initTestProjects() {
        templateAdapter = new HomeTemplateAdapter(getActivity(), null);
        templateRv.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayout.HORIZONTAL, false));
        templateRv.setAdapter(templateAdapter);
        notifyTestProjects();
    }

    private void initStopButton() {
        stopExpTv.setOnClickListener(v -> {
            final DialogView dialogView = new DialogView(getContext());
            dialogView.setTitle("终止实验");
            dialogView.setTextContent("终止后无法继续该实验，是否确认终止？");
            dialogView.setOnClickListener("仍然终止", new DialogView.OnSureListener() {
                @Override
                public void onSureClick(String content) {
                    if (currentController == null) {
                        return;
                    }
                    currentController.stopExp();
                    sideSlipLayout.close(true);
                    ToastUtils.get().showText("终止实验成功");
                    renderHandler.obtainMessage(MSG_RENDER).sendToTarget();
                }
            }).show();
        });
    }


    /**
     * 实验状态View
     */
    private void addExperimentStatusView() {
        View.inflate(getActivity(), R.layout.layout_experment_status, connectWrapperFl);
        //实验的三种状态：新建实验
        expNewBtn = connectWrapperFl.findViewById(R.id.experiment_new_btn);

        //实验的三种状态：实验运行中
        expRunningLl = connectWrapperFl.findViewById(R.id.experiment_running_ll);
        startTimeTv = connectWrapperFl.findViewById(R.id.start_time_tv);
        endTimeTv = connectWrapperFl.findViewById(R.id.end_time_tv);
        leftTimeTv = connectWrapperFl.findViewById(R.id.plan_time_tv);
        processTv = connectWrapperFl.findViewById(R.id.tv_process);
        progressView = connectWrapperFl.findViewById(R.id.progress_view);

        //实验的三种状态：实验结束
        expFinishedCl = connectWrapperFl.findViewById(R.id.experiment_finished_cl);
        View tvToNewExpState = connectWrapperFl.findViewById(R.id.tv_to_new_exp_state);
        View tvCheckExpResult = connectWrapperFl.findViewById(R.id.tv_check_exp_result);
        tvToNewExpState.setOnClickListener(v -> {
            // TODO: 2019/10/10 回到显示新建实验的界面  需要修改实验状态
            currentController.setExpState(Constants.EXP_STATE_IDLE);
            changeExpColumnState(currentController.getExpState());
        });
        tvCheckExpResult.setOnClickListener(v -> {
            Intent expResult = new Intent(getContext(), ExpResultActivity.class);
            expResult.putExtra("fileName", currentController.getExpInfo().getName());
            HomeFragment.this.startActivity(expResult);
            currentController.setExpState(Constants.EXP_STATE_IDLE);
            changeExpColumnState(currentController.getExpState());
        });
        expNewBtn.setOnClickListener(v -> {
            //新建实验
            Intent newExpIntent = new Intent(getContext(), ExpNewExperimentActivity.class);
            HomeFragment.this.startActivity(newExpIntent);
        });
    }

    @OnClick({R.id.fl_check_project, R.id.exp_run_btn})
    public void click(View view) {
        switch (view.getId()) {
            case R.id.fl_check_project:
                Intent managerIntent = new Intent(getContext(), TemplatesManagerActivity.class);
                HomeFragment.this.startActivity(managerIntent);
                break;
            case R.id.exp_run_btn:
                //去往实验运行中界面
                Intent intent = new Intent(getContext(), ExpRunningActivity.class);
                startActivity(intent);
                break;
            default:
                break;
        }
    }


    /**
     * 实验状态发生变化
     *
     * @paramstate 状态值
     */
    private void changeExpColumnState(int state) {
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                setFlBackground(state);
                switch (state) {
                    case Constants.EXP_STATE_IDLE:
                        if (sideSlipLayout != null) {
                            sideSlipLayout.setLockDrag(true);
                        }
                        renderHandler.removeMessages(MSG_RENDER);
                        checkConnection(expNewBtn);
                        break;
                    case Constants.EXP_STATE_RUNNING:
                        if (sideSlipLayout != null) {
                            sideSlipLayout.setLockDrag(false);
                        }
                        renderHandler.obtainMessage(MSG_RENDER).sendToTarget();
                        checkConnection(expRunningLl);

                        break;
                    case Constants.EXP_STATE_FINISH:
                        if (sideSlipLayout != null) {
                            sideSlipLayout.setLockDrag(true);
                        }
                        renderHandler.removeMessages(MSG_RENDER);
                        checkConnection(expFinishedCl);
                        break;
                    case Constants.EXP_STATE_INTERRUPT:
                        if (sideSlipLayout != null) {
                            sideSlipLayout.setLockDrag(true);
                        }
                        renderHandler.removeMessages(MSG_RENDER);
                        showExceptionDialog();
                        checkConnection(expFinishedCl);
                        break;
                    default:
                }
            }
        });

    }

    private void showExceptionDialog() {
        new DialogView(getContext()).setTitle("实验异常终止")
                .setTextContent(ExpException.getDesc(currentController.getExpInfo().getFinishCause()))//ExpKit.getExpErrorMsg()
                .setOnClickListener(true, "确认", null).show();
    }

    /**
     * 更新实验状态的UI:新建实验、运行中、实验结束
     */
    private void notifyExpState(View view) {
        if (view.getId() == expNewBtn.getId()) {
            expNewBtn.setVisibility(View.VISIBLE);
            expRunningLl.setVisibility(View.GONE);
            expFinishedCl.setVisibility(View.GONE);
            if (expRunBtn != null) {
                expRunBtn.setVisibility(View.GONE);
            }
        } else if (view.getId() == expRunningLl.getId()) {
            expRunningLl.setVisibility(View.VISIBLE);
            if (expRunBtn != null) {
                expRunBtn.setVisibility(View.VISIBLE);
            }
            expNewBtn.setVisibility(View.GONE);
            expFinishedCl.setVisibility(View.GONE);
        }
        if (view.getId() == expFinishedCl.getId()) {
            expFinishedCl.setVisibility(View.VISIBLE);
            expNewBtn.setVisibility(View.GONE);
            expRunningLl.setVisibility(View.GONE);
            if (expRunBtn != null) {
                expRunBtn.setVisibility(View.GONE);
            }
        }
    }

    /**
     * 检查连接状态，如果当前设备没有连接，显示无法连接界面
     *
     * @param view
     */
    private void checkConnection(View view) {
        notifyExpState(view);
    }

    public void setExperimentProgress() {
        if (currentController == null) {
            return;
        }
        Bundle bundle = currentController.getRunSummary();
        if (bundle != null) {
            //开始时间点
            long beginTime = bundle.getLong("beginTime");
            startTimeTv.setText(AutoUtil.getHour(beginTime));
            //预计总运行时间
            long planTime = bundle.getLong("planTime");
            //预计剩余时间
            long leftTime = bundle.getLong("leftTime");
            //预计结束时间点
            endTimeTv.setText(AutoUtil.getHour(planTime + beginTime));
            if (beginTime != 0) {
                //剩余时间
                String left = AutoUtil.getHourAndMin(leftTime);
                leftTimeTv.setText(left);
                float percent = (System.currentTimeMillis() - beginTime) * 1f / planTime;
                if (percent >= 0) {
                    if (percent > 1) {
                        percent = 1;
                    }
                    processTv.setText(String.format(Locale.CHINA, "%d%%", (int) (percent * 100)));
                    progressView.setProcess(percent);
                }
            }
        }

    }



    /**
     * 每隔一秒钟更新进度条
     */
    private static class UiHandler extends Handler {
        private WeakReference<HomeFragment> mFragment;

        private UiHandler(HomeFragment fragment) {
            mFragment = new WeakReference<>(fragment);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            HomeFragment fragment = mFragment.get();
            if (fragment != null) {
                if (msg.what == MSG_RENDER) {
                    fragment.setExperimentProgress();
                    sendEmptyMessageDelayed(MSG_RENDER, 1000);
                }
            }
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        notifyTestProjects();
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (getUserVisibleHint()) {
            notifyTestProjects();
            if (currentController == null) {
                return;
            }
            if (currentController.getExpInfo() == null) {
                changeExpColumnState(currentController.getExpState());
                return;
            }
            DBManager.get().getExpByName(currentController.getExpInfo().getName(), entity -> {
                if (entity != null) {
                    if (currentController.getExpState() == Constants.EXP_STATE_FINISH && entity.isRead()) {
                        currentController.setExpState(Constants.EXP_STATE_IDLE);
                    }
                }
                changeExpColumnState(currentController.getExpState());
            });

        }
    }
}
